#include <glib.h>
#include <glib-object.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <sys/types.h>
#include <dirent.h>
#include "vercmp.h"
#include "arch_pkg.h"
//#include <alpm.h>
//

/*  
typedef enum {
   ARCH_TYPE_I686 = 0, 
   ARCH_TYPE_X86_64, 
   ARCH_TYPE_ANY, 
   ARCH_TYPE_NO_ARCH, 
}EArchType_t;
*/
const TArchMap_t g_arch_map_tbl[] = {
    { "i686" , ARCH_TYPE_I686 },
    { "x86_64" , ARCH_TYPE_X86_64},
    { "any" , ARCH_TYPE_ANY },
    { NULL,  ARCH_TYPE_NO_ARCH}
};

struct _GArchPkgPrivate {
    char    *pkg_name;
    char    *pkg_ver;
    char    *pkg_relver;
    char    *pkg_arch_name;
    char    *pkg_suffx_name;
    char    *pkg_file_name;
    char    *pkg_full_ver;
    int     pkg_relver_num;
    gboolean b_pkg_avail;
    EArchType_t arch_type;
};//__attribute__((packed)) TArchPkg_t ;

const char *g_pkg_subfix[] = {
    ".pkg.tar.xz", 
    ".pkg.tar.gz", 
    ".pkg.tar.bz2", 
    NULL
};


static void free_priv_arch_pkg(GArchPkgPrivate *p_arch_pkg_priv);


G_DEFINE_TYPE(GArchPkg, g_arch_pkg, G_TYPE_OBJECT);

static void g_arch_pkg_constructed(GObject *object)
{
    GArchPkg *arch_pkg = G_ARCH_PKG(object);
    //arch_pkg->priv
}

static void g_arch_pkg_finalize(GObject *object)
{
    GArchPkg *arch_pkg = G_ARCH_PKG(object);
    GArchPkgPrivate *p_arch_pkg_priv = arch_pkg->priv;
    //if (TRUE == p_arch_pkg_priv->b_pkg_avail) {
        free_priv_arch_pkg(p_arch_pkg_priv);
    //}
    if (G_OBJECT_CLASS(g_arch_pkg_parent_class)->finalize) {
        (*G_OBJECT_CLASS(g_arch_pkg_parent_class)->finalize) (object);
    }
}

void free_priv_arch_pkg(GArchPkgPrivate *p_arch_pkg_priv)
{
    if (NULL == p_arch_pkg_priv) {
        g_printf("error: free_arch_pkg() --> NULL == p_arch_pkg_priv fail\n");
        return;
    }

    if (NULL != p_arch_pkg_priv->pkg_name) {
        g_free(p_arch_pkg_priv->pkg_name);
        p_arch_pkg_priv->pkg_name = NULL;
    }
    if (NULL != p_arch_pkg_priv->pkg_full_ver ) {
        g_free(p_arch_pkg_priv->pkg_full_ver );
        p_arch_pkg_priv->pkg_full_ver = NULL;
    }


    if (NULL != p_arch_pkg_priv->pkg_ver) {
        g_free(p_arch_pkg_priv->pkg_ver);
        p_arch_pkg_priv->pkg_ver = NULL;
    }
    if (NULL != p_arch_pkg_priv->pkg_relver) {
        g_free(p_arch_pkg_priv->pkg_relver);
        p_arch_pkg_priv->pkg_relver = NULL;
    }
    if (NULL != p_arch_pkg_priv->pkg_arch_name) {
        g_free(p_arch_pkg_priv->pkg_arch_name);
        p_arch_pkg_priv->pkg_arch_name = NULL;
    }
    if (NULL != p_arch_pkg_priv->pkg_suffx_name) {
        g_free(p_arch_pkg_priv->pkg_suffx_name);
        p_arch_pkg_priv->pkg_suffx_name = NULL;
    }
    if (NULL != p_arch_pkg_priv->pkg_file_name ) {
        g_free(p_arch_pkg_priv->pkg_file_name );
        p_arch_pkg_priv->pkg_file_name = NULL;

    }
    p_arch_pkg_priv->b_pkg_avail = FALSE;
}



static void g_arch_pkg_set_property(GObject *object,
                                    guint prop_id,
                                    const GValue *value,
                                    GParamSpec *pspec)
{
    GArchPkg *arch_pkg = G_ARCH_PKG(object);
    switch (prop_id) {
        //case PROP_xxx:
        //g_value_
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);

    }//end switch

}

static void g_arch_pkg_get_property(GObject *object,
                                    guint prop_id,
                                    GValue *value,
                                    GParamSpec *pspec)
{
    GArchPkg *arch_pkg = G_ARCH_PKG(object);
    switch (prop_id) {
        //case PROP_xxx:
        //g_value_
        default:
            G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);

    }//end switch

}


static void g_arch_pkg_class_init(GArchPkgClass *klass)
{
    GObjectClass *gobject_class = G_OBJECT_CLASS(klass);

    g_type_class_add_private (klass, sizeof(GArchPkgPrivate));
    gobject_class->finalize     = g_arch_pkg_finalize;
    gobject_class->constructed  = g_arch_pkg_constructed;
    gobject_class->set_property = g_arch_pkg_set_property;
    gobject_class->get_property = g_arch_pkg_get_property;

}

static void g_arch_pkg_init(GArchPkg *arch_pkg)
{
    arch_pkg->priv = G_TYPE_INSTANCE_GET_PRIVATE(arch_pkg, G_TYPE_ARCH_PKG, GArchPkgPrivate);
    arch_pkg->priv->pkg_name = NULL;
    arch_pkg->priv->pkg_full_ver = NULL;
    arch_pkg->priv->pkg_ver = NULL;
    arch_pkg->priv->pkg_relver = NULL;
    arch_pkg->priv->pkg_relver_num = 0;
    arch_pkg->priv->pkg_arch_name = NULL;
    arch_pkg->priv->pkg_suffx_name = NULL;
    arch_pkg->priv->pkg_file_name = NULL;
    arch_pkg->priv->arch_type = ARCH_TYPE_I686;
    arch_pkg->priv->b_pkg_avail = FALSE;
}

GArchPkg *g_arch_pkg_new(void) 
{
    GArchPkg *p_arch_pkg;
    p_arch_pkg = g_object_new(G_TYPE_ARCH_PKG, NULL);
    return p_arch_pkg;
}

void g_arch_pkg_print_info(GArchPkg *arch_pkg)
{
    GArchPkgPrivate *p_arch_pkg_priv;
    g_return_if_fail(G_IS_ARCH_PKG(arch_pkg));
    p_arch_pkg_priv = arch_pkg->priv;
    if (FALSE ==  p_arch_pkg_priv->b_pkg_avail) {
        g_printf("b_pkg_avail == FALSE\r\n");
        return;
    }
    g_printf("===============================\n");
    g_printf("pkg_name \t= %s\n", p_arch_pkg_priv->pkg_name);
    g_printf("pkg_full_ver \t= %s\n", p_arch_pkg_priv->pkg_full_ver);
    g_printf("pkg_ver \t= %s\n", p_arch_pkg_priv->pkg_ver);
    g_printf("pkg_relver \t= %s\n", p_arch_pkg_priv->pkg_relver);
    g_printf("pkg_relver_num \t= %d\n", p_arch_pkg_priv->pkg_relver_num);
    g_printf("pkg_arch_name \t= %s\n", p_arch_pkg_priv->pkg_arch_name);
    g_printf("pkg_suffx_name \t= %s\n",  p_arch_pkg_priv->pkg_suffx_name);
    g_printf("pkg_file_name \t= %s\n", p_arch_pkg_priv->pkg_file_name);
    switch (p_arch_pkg_priv->arch_type) {
        case ARCH_TYPE_ANY:
            g_printf("pkg arch type \t= ARCH_TYPE_ANY\n");
            break;

        case ARCH_TYPE_I686:
            g_printf("pkg arch type \t= ARCH_TYPE_I686\n");
            break;

        case ARCH_TYPE_X86_64:
            g_printf("pkg arch type \t= ARCH_TYPE_X86_64\n");
            break;

        case ARCH_TYPE_NO_ARCH:
            g_printf("pkg arch type \t= ARCH_TYPE_NO_ARCH\n");
            break;

        default:
            g_printf("pkg arch type \t= unkown\n");
            break;

    }//end
    g_printf("-----------------------------------\n\n");
 
}



gboolean parse_arch_pkg_priv(GArchPkgPrivate *p_arch_pkg_priv, const char *pkg_str)
{
    //char *move_ptr;
    int inx;
    char *find_ptr; 
    char find_len;
    char *last_ptr;
    char *tmp_pkg_str;
    gboolean bIsNoArchPkg;
    p_arch_pkg_priv->pkg_file_name = strdup(pkg_str);
    tmp_pkg_str = strdup(pkg_str);
    //g_printf("file_name = %s\n", p_arch_pkg_priv->pkg_file_name);
    //move_ptr = tmp_pkg_str;

    //find -i686.pkg.tar.gz
    //virtualbox_bin-3.1.0-1-i686.pkg.tar.gz
    find_ptr = strrchr(tmp_pkg_str, '-');
    if (NULL == find_ptr) {
        g_free(tmp_pkg_str);
        return FALSE;
    }
    // -i686.pkg.tar.gz
    // or -1.pkg.tar.gz
    //printf("<1> -i686.pkg.tar.gz  find ptr = %s\n", find_ptr);
    *find_ptr = '\0';
    //find i686
    //or find relver
    find_ptr++;
    last_ptr = find_ptr;
    //virtualbox_bin-3.1.0-1-i686.pkg.tar.gz
    //inotify-tools-3.13-1.pkg.tar.gz
    // last_ptr -> i 
    // or last_ptr -> 1
    find_ptr = strchr(find_ptr, '.');
    if (NULL == find_ptr) {
        g_free(tmp_pkg_str);
        return FALSE;
    }
    //printf("<2> i686  find ptr = %s\n", find_ptr);
    *find_ptr = '\0';
    find_ptr++;
    //g_printf("FLAG: last_ptr = %s\n", last_ptr);
    //g_printf("FLAG: find ptr = %s\n", find_ptr);

    /*  
    if (strcmp(find_ptr, "pkg.tar.gz") == 0) {
        p_arch_pkg_priv->pkg_relver =  strdup(last_ptr);
        p_arch_pkg_priv->pkg_relver_num = atoi(p_arch_pkg_priv->pkg_relver);

        p_arch_pkg_priv->pkg_arch_name =  strdup("no");
        p_arch_pkg_priv->pkg_suffx_name = strdup("pkg.tar.gz");
        g_printf("pkg_no_arch file = %s\n", p_arch_pkg_priv->pkg_file_name);
        bIsNoArchPkg  = TRUE;
    } else {
        bIsNoArchPkg  = FALSE;
        g_printf("have_arch file = %s\n", p_arch_pkg_priv->pkg_file_name);
    }
   */ 
    //if (FALSE == bIsNoArchPkg) { 
        p_arch_pkg_priv->pkg_arch_name =  strdup(last_ptr);
        p_arch_pkg_priv->arch_type = ARCH_TYPE_NO_ARCH;
        for ( inx = 0; inx < sizeof(g_arch_map_tbl) / sizeof(TArchMap_t); inx++) {
            if (0 == strcmp(p_arch_pkg_priv->pkg_arch_name , g_arch_map_tbl[inx].str_arch_name)) {
                p_arch_pkg_priv->arch_type = g_arch_map_tbl[inx].arch_type;
            }
        }
        switch (p_arch_pkg_priv->arch_type) {
            case ARCH_TYPE_NO_ARCH:
                g_printf("pkg_no_arch: %s\n", p_arch_pkg_priv->pkg_file_name); 
                break;

            case ARCH_TYPE_I686:
                break;

            case ARCH_TYPE_X86_64: 
                break;

            case ARCH_TYPE_ANY: 
                break;

            default:
                break;

        }//end switch
        

        if (0 != strcmp(p_arch_pkg_priv->pkg_arch_name , "i686")) {
            if (0 != strcmp(p_arch_pkg_priv->pkg_arch_name , "x86_64")) {
                if (0 != strcmp(p_arch_pkg_priv->pkg_arch_name , "any")) {
                    if (strcmp(find_ptr, "pkg.tar.gz") == 0) {
                        p_arch_pkg_priv->pkg_relver =  strdup(last_ptr);
                        p_arch_pkg_priv->pkg_relver_num = atoi(p_arch_pkg_priv->pkg_relver);
                        g_free(p_arch_pkg_priv->pkg_arch_name);
                        p_arch_pkg_priv->pkg_arch_name =  strdup("no_arch");
                        p_arch_pkg_priv->pkg_suffx_name = strdup(find_ptr); //strdup("pkg.tar.gz");
                        p_arch_pkg_priv->arch_type = ARCH_TYPE_NO_ARCH;
                        //g_printf("pkg_no_arch file = %s\n", p_arch_pkg_priv->pkg_file_name);
                    } else {
                        if (strcmp(find_ptr, "pkg.tar.bz2") == 0) {
                            p_arch_pkg_priv->pkg_relver =  strdup(last_ptr);
                            p_arch_pkg_priv->pkg_relver_num = atoi(p_arch_pkg_priv->pkg_relver);
                            g_free(p_arch_pkg_priv->pkg_arch_name);
                            p_arch_pkg_priv->pkg_arch_name =  strdup("no_arch");
                            p_arch_pkg_priv->pkg_suffx_name = strdup(find_ptr);//strdup("pkg.tar.bz2");
                            p_arch_pkg_priv->arch_type = ARCH_TYPE_NO_ARCH;
                        } else {
                            g_printf("pkg_err: %s\n", p_arch_pkg_priv->pkg_file_name); 
                            g_free(tmp_pkg_str);
                            return FALSE;
                        }
                    }//end pkg.tar.gz
                } else {
                    p_arch_pkg_priv->pkg_suffx_name = strdup(find_ptr);
                    p_arch_pkg_priv->arch_type = ARCH_TYPE_ANY;
                }//end any
            } else {
                p_arch_pkg_priv->pkg_suffx_name = strdup(find_ptr);
                p_arch_pkg_priv->arch_type = ARCH_TYPE_X86_64;
            }//end x86_64 
        } else {
            p_arch_pkg_priv->pkg_suffx_name = strdup(find_ptr);
            p_arch_pkg_priv->arch_type = ARCH_TYPE_I686;
        }//end i686
        if (ARCH_TYPE_NO_ARCH != p_arch_pkg_priv->arch_type) {
            //find relver
            //virtualbox_bin-3.1.0-1
            find_ptr = strrchr(tmp_pkg_str, '-');
            if (NULL == find_ptr) {
                g_free(tmp_pkg_str);
                return FALSE;
            }
            //printf("<3> relver find ptr = %s\n", find_ptr);
            *find_ptr = '\0';
            find_ptr++;
            p_arch_pkg_priv->pkg_relver =  strdup(find_ptr);
            p_arch_pkg_priv->pkg_relver_num = atoi(p_arch_pkg_priv->pkg_relver);
        } else {
            //skip find relver
        }

    //} 
    //find ver 
    find_ptr = strrchr(tmp_pkg_str, '-');
    if (NULL == find_ptr) {
        g_free(tmp_pkg_str);
        return FALSE;
    }
    //printf("<4> ver find ptr = %s\n", find_ptr);
    *find_ptr = '\0';
    find_ptr++;
    p_arch_pkg_priv->pkg_ver =  strdup(find_ptr);

    //tmp_pkg_str 
    p_arch_pkg_priv->pkg_name =  strdup(tmp_pkg_str);

    //if (NULL != move_ptr) {
        //p_arch_pkg_priv->pkg_suffx_name = strdup(move_ptr);
    //}
    p_arch_pkg_priv->pkg_full_ver = g_strdup_printf("%s-%s", p_arch_pkg_priv->pkg_ver, p_arch_pkg_priv->pkg_relver);
    p_arch_pkg_priv->b_pkg_avail = TRUE;
    g_free(tmp_pkg_str);
    return TRUE;
}


gboolean g_arch_pkg_parse_by_str(GArchPkg *arch_pkg, const char *pkg_str)
{
    GArchPkgPrivate *p_arch_pkg_priv;
    g_return_if_fail(G_IS_ARCH_PKG(arch_pkg));
    p_arch_pkg_priv = arch_pkg->priv;
    if (TRUE == p_arch_pkg_priv->b_pkg_avail) {
        free_priv_arch_pkg(p_arch_pkg_priv);
    }

    if (FALSE == parse_arch_pkg_priv(p_arch_pkg_priv, pkg_str)) {
        free_priv_arch_pkg(p_arch_pkg_priv);
        //p_arch_pkg_priv->b_pkg_avail = FALSE;
        return FALSE;
    }
    return TRUE;
}

void g_arch_pkg_delete_delete_file(GArchPkg *arch_pkg, const char *dir_name, gboolean b_unlink_en)
{

    char del_filename[255];
    GArchPkgPrivate *p_arch_pkg_priv;
    g_return_if_fail(G_IS_ARCH_PKG(arch_pkg));
    p_arch_pkg_priv = arch_pkg->priv;
    if (FALSE == p_arch_pkg_priv->b_pkg_avail) {
        g_printf("b_pkg_avail == FALSE\n");
        return;
    }
    snprintf(del_filename, sizeof(del_filename), "%s/%s", dir_name, p_arch_pkg_priv->pkg_file_name);
    if (TRUE == b_unlink_en) {
        if (access(del_filename, W_OK) == 0) {
            if (!unlink(del_filename)) {
                g_printf("delete %s success\n", del_filename);
            } else {
                    g_printf("delete %s faile\n", del_filename);
            }
        } else {
            g_printf("!!! access(%s, W_OK) != 0\n", del_filename);
        }
    } else {
        g_printf("test : delete %s \n", del_filename);
    }
}
 

void print_arch_pkg(TArchPkg_t *p_arch_pkg)
{
    g_printf("===============================\n");
    g_printf("pkg_name \t= %s\n", p_arch_pkg->pkg_name);
    g_printf("pkg_full_ver \t= %s\n", p_arch_pkg->pkg_full_ver);
    g_printf("pkg_ver \t= %s\n", p_arch_pkg->pkg_ver);
    g_printf("pkg_relver \t= %s\n", p_arch_pkg->pkg_relver);
    g_printf("pkg_relver_num \t= %d\n", p_arch_pkg->pkg_relver_num);
    g_printf("pkg_arch_name \t= %s\n", p_arch_pkg->pkg_arch_name);
    g_printf("pkg_suffx_name \t= %s\n",  p_arch_pkg->pkg_suffx_name);
    g_printf("pkg_file_name \t= %s\n", p_arch_pkg->pkg_file_name);
    switch (p_arch_pkg->arch_type) {
        case ARCH_TYPE_ANY:
            g_printf("pkg arch type \t= ARCH_TYPE_ANY\n");
            break;

        case ARCH_TYPE_I686:
            g_printf("pkg arch type \t= ARCH_TYPE_I686\n");
            break;

        case ARCH_TYPE_X86_64:
            g_printf("pkg arch type \t= ARCH_TYPE_X86_64\n");
            break;

        case ARCH_TYPE_NO_ARCH:
            g_printf("pkg arch type \t= ARCH_TYPE_NO_ARCH\n");
            break;

        default:
            g_printf("pkg arch type \t= unkown\n");
            break;

    }//end
    g_printf("-----------------------------------\n\n");
    

}


int parse_arch_pkg(TArchPkg_t *p_arch_pkg, const char *pkg_str)
{
    //char *move_ptr;
    char *find_ptr; 
    char find_len;
    char *last_ptr;
    char *tmp_pkg_str;
    gboolean bIsNoArchPkg;
    p_arch_pkg->pkg_file_name = strdup(pkg_str);
    tmp_pkg_str = strdup(pkg_str);
    //g_printf("file_name = %s\n", p_arch_pkg->pkg_file_name);
    //move_ptr = tmp_pkg_str;

    //find -i686.pkg.tar.gz
    //virtualbox_bin-3.1.0-1-i686.pkg.tar.gz
    find_ptr = strrchr(tmp_pkg_str, '-');
    if (NULL == find_ptr) {
        g_free(tmp_pkg_str);
        return -1;
    }
    // -i686.pkg.tar.gz
    // or -1.pkg.tar.gz
    //printf("<1> -i686.pkg.tar.gz  find ptr = %s\n", find_ptr);
    *find_ptr = '\0';
    //find i686
    //or find relver
    find_ptr++;
    last_ptr = find_ptr;
    //virtualbox_bin-3.1.0-1-i686.pkg.tar.gz
    //inotify-tools-3.13-1.pkg.tar.gz
    // last_ptr -> i 
    // or last_ptr -> 1
    find_ptr = strchr(find_ptr, '.');
    if (NULL == find_ptr) {
        g_free(tmp_pkg_str);
        return -1;
    }
    //printf("<2> i686  find ptr = %s\n", find_ptr);
    *find_ptr = '\0';
    find_ptr++;
    //g_printf("FLAG: last_ptr = %s\n", last_ptr);
    //g_printf("FLAG: find ptr = %s\n", find_ptr);

    /*  
    if (strcmp(find_ptr, "pkg.tar.gz") == 0) {
        p_arch_pkg->pkg_relver =  strdup(last_ptr);
        p_arch_pkg->pkg_relver_num = atoi(p_arch_pkg->pkg_relver);

        p_arch_pkg->pkg_arch_name =  strdup("no");
        p_arch_pkg->pkg_suffx_name = strdup("pkg.tar.gz");
        g_printf("pkg_no_arch file = %s\n", p_arch_pkg->pkg_file_name);
        bIsNoArchPkg  = TRUE;
    } else {
        bIsNoArchPkg  = FALSE;
        g_printf("have_arch file = %s\n", p_arch_pkg->pkg_file_name);
    }
   */ 
    //if (FALSE == bIsNoArchPkg) { 
        p_arch_pkg->pkg_arch_name =  strdup(last_ptr);
        if (0 != strcmp(p_arch_pkg->pkg_arch_name , "i686")) {
            if (0 != strcmp(p_arch_pkg->pkg_arch_name , "x86_64")) {
                if (0 != strcmp(p_arch_pkg->pkg_arch_name , "any")) {
                    if (strcmp(find_ptr, "pkg.tar.gz") == 0) {
                        p_arch_pkg->pkg_relver =  strdup(last_ptr);
                        p_arch_pkg->pkg_relver_num = atoi(p_arch_pkg->pkg_relver);
                        g_free(p_arch_pkg->pkg_arch_name);
                        p_arch_pkg->pkg_arch_name =  strdup("no_arch");
                        p_arch_pkg->pkg_suffx_name = strdup(find_ptr); //strdup("pkg.tar.gz");
                        p_arch_pkg->arch_type = ARCH_TYPE_NO_ARCH;
                        //g_printf("pkg_no_arch file = %s\n", p_arch_pkg->pkg_file_name);
                    } else {
                        if (strcmp(find_ptr, "pkg.tar.bz2") == 0) {
                            p_arch_pkg->pkg_relver =  strdup(last_ptr);
                            p_arch_pkg->pkg_relver_num = atoi(p_arch_pkg->pkg_relver);
                            g_free(p_arch_pkg->pkg_arch_name);
                            p_arch_pkg->pkg_arch_name =  strdup("no_arch");
                            p_arch_pkg->pkg_suffx_name = strdup(find_ptr);//strdup("pkg.tar.bz2");
                            p_arch_pkg->arch_type = ARCH_TYPE_NO_ARCH;
                        } else {
                            g_printf("pkg_err: %s\n", p_arch_pkg->pkg_file_name); 
                            g_free(tmp_pkg_str);
                            return -1;
                        }
                    }//end pkg.tar.gz
                } else {
                    p_arch_pkg->pkg_suffx_name = strdup(find_ptr);
                    p_arch_pkg->arch_type = ARCH_TYPE_ANY;
                }//end any
            } else {
                p_arch_pkg->pkg_suffx_name = strdup(find_ptr);
                p_arch_pkg->arch_type = ARCH_TYPE_X86_64;
            }//end x86_64 
        } else {
            p_arch_pkg->pkg_suffx_name = strdup(find_ptr);
            p_arch_pkg->arch_type = ARCH_TYPE_I686;
        }//end i686
        if (ARCH_TYPE_NO_ARCH != p_arch_pkg->arch_type) {
            //find relver
            //virtualbox_bin-3.1.0-1
            find_ptr = strrchr(tmp_pkg_str, '-');
            if (NULL == find_ptr) {
                g_free(tmp_pkg_str);
                return -1;
            }
            //printf("<3> relver find ptr = %s\n", find_ptr);
            *find_ptr = '\0';
            find_ptr++;
            p_arch_pkg->pkg_relver =  strdup(find_ptr);
            p_arch_pkg->pkg_relver_num = atoi(p_arch_pkg->pkg_relver);
        } else {
            //skip find relver
        }

    //} 
    //find ver 
    find_ptr = strrchr(tmp_pkg_str, '-');
    if (NULL == find_ptr) {
        g_free(tmp_pkg_str);
        return -1;
    }
    //printf("<4> ver find ptr = %s\n", find_ptr);
    *find_ptr = '\0';
    find_ptr++;
    p_arch_pkg->pkg_ver =  strdup(find_ptr);

    //tmp_pkg_str 
    p_arch_pkg->pkg_name =  strdup(tmp_pkg_str);

    //if (NULL != move_ptr) {
        //p_arch_pkg->pkg_suffx_name = strdup(move_ptr);
    //}
    p_arch_pkg->pkg_full_ver = g_strdup_printf("%s-%s", p_arch_pkg->pkg_ver, p_arch_pkg->pkg_relver);

    g_free(tmp_pkg_str);
    return 0;
}


void init_arch_pkg(TArchPkg_t *p_arch_pkg)
{
    p_arch_pkg->pkg_name = NULL;
    p_arch_pkg->pkg_full_ver = NULL;
    p_arch_pkg->pkg_ver = NULL;
    p_arch_pkg->pkg_relver = NULL;
    p_arch_pkg->pkg_relver_num = 0;
    p_arch_pkg->pkg_arch_name = NULL;
    p_arch_pkg->pkg_suffx_name = NULL;
    p_arch_pkg->pkg_file_name = NULL;
    p_arch_pkg->arch_type = ARCH_TYPE_I686;
    //arch_pkg->priv->b_pkg_avail = FALSE;
}


TArchPkg_t *arch_pkg_new(void)
{
    TArchPkg_t  *p_arch_pkg;
    p_arch_pkg = g_new(TArchPkg_t, 1);
    if (NULL == p_arch_pkg) {
        g_printf("error: g_new(TArchPkg_t) fail\n");
        exit(-1);
    }
    init_arch_pkg(p_arch_pkg);
}


void free_arch_pkg(TArchPkg_t *p_arch_pkg)
{
    if (NULL == p_arch_pkg) {
        g_printf("error: free_arch_pkg() --> NULL == p_arch_pkg fail\n");
        return;
    }

    if (NULL != p_arch_pkg->pkg_name) {
        g_free(p_arch_pkg->pkg_name);
        p_arch_pkg->pkg_name = NULL;
    }
    if (NULL != p_arch_pkg->pkg_full_ver ) {
        g_free(p_arch_pkg->pkg_full_ver );
        p_arch_pkg->pkg_full_ver = NULL;
    }


    if (NULL != p_arch_pkg->pkg_ver) {
        g_free(p_arch_pkg->pkg_ver);
        p_arch_pkg->pkg_ver = NULL;
    }
    if (NULL != p_arch_pkg->pkg_relver) {
        g_free(p_arch_pkg->pkg_relver);
        p_arch_pkg->pkg_relver = NULL;
    }
    if (NULL != p_arch_pkg->pkg_arch_name) {
        g_free(p_arch_pkg->pkg_arch_name);
        p_arch_pkg->pkg_arch_name = NULL;
    }
    if (NULL != p_arch_pkg->pkg_suffx_name) {
        g_free(p_arch_pkg->pkg_suffx_name);
        p_arch_pkg->pkg_suffx_name = NULL;
    }
    if (NULL != p_arch_pkg->pkg_file_name ) {
        g_free(p_arch_pkg->pkg_file_name );
        p_arch_pkg->pkg_file_name = NULL;

    }
}

void arch_pkg_free(TArchPkg_t *p_arch_pkg)
{
    if (NULL == p_arch_pkg) {
        g_printf("error: free --> NULL == p_arch_pkg fail\n");
        return;
    }
    free_arch_pkg(p_arch_pkg);
    g_free(p_arch_pkg);
}

GList *scan_pkgs(char *dir)
{
    DIR *dp;
    struct dirent *entry;
    struct stat statbuf;
    GList *p_pkg_list = NULL;
    TArchPkg_t *p_arch_pkg;
    //depth = depth;
    if ((dp = opendir(dir)) == NULL) {
        fprintf(stderr, "cannot opendir directory: %s\r\n", dir);
        return ;
    }//end if
    chdir(dir);
    while ((entry = readdir(dp)) != NULL) {
        lstat(entry->d_name, &statbuf);
        if (S_ISREG(statbuf.st_mode)) {
            if (0 == chk_is_arch_pkg_file(entry->d_name)) {
                p_arch_pkg = arch_pkg_new();
                init_arch_pkg(p_arch_pkg);
                if (parse_arch_pkg(p_arch_pkg, entry->d_name) == 0) {
                    //g_printf("g_list_append() start\n");
                    p_pkg_list = g_list_append(p_pkg_list, p_arch_pkg);
                    //g_printf("g_list_append() over\n");
                } else {
                    arch_pkg_free(p_arch_pkg);
                }

            } else {
                g_printf("%s not arch pkg file\n", entry->d_name);
            }
        }
        /* 
        g_printf("telldir(%s) = %d\n", entry->d_name, telldir(dp));
        if (S_ISDIR(statbuf.st_mode)) {
            if ((strcmp(".", entry->d_name) == 0) || 
                (strcmp("..", entry->d_name) == 0)) {
                continue;
            }//end if
            g_printf("%*s%s/\n", depth, "", entry->d_name);
            printdir(entry->d_name, depth + 4);
        } else {
            g_printf("%*s%s\n", depth, "", entry->d_name);
        }
        */
    } //end 
    //chdir("..");
    closedir(dp);
    return p_pkg_list;
}

void show_pkg(gpointer pkg_ptr, gpointer user_data)
{
    TArchPkg_t *p_arch_pkg;
    p_arch_pkg = (TArchPkg_t *) pkg_ptr;
    print_arch_pkg(p_arch_pkg);
}

void free_pkg(gpointer pkg_ptr, gpointer user_data)
{
    TArchPkg_t *p_arch_pkg;
    p_arch_pkg = (TArchPkg_t *) pkg_ptr;
    arch_pkg_free(p_arch_pkg);
}


void show_all_list_pkg(GList *list)
{
    g_list_foreach(list, show_pkg, NULL);
}

void free_all_list_pkg(GList *list)
{
    g_list_foreach(list, free_pkg, NULL);
}

int chk_is_arch_pkg_file(const char *p_file_name)
{

    gint i;
    char *p_pkg_subfix_ptr = NULL;
    for (i = 0; i < (sizeof(g_pkg_subfix) / sizeof(const char *)); i++) {
        p_pkg_subfix_ptr = (char*)&g_pkg_subfix[i];
        if (strstr(p_file_name, p_pkg_subfix_ptr) != NULL) {
            return 0;
        }
    }//end for

//--------------error ----------------
//  char **pp_pkg_subfix_ptr = NULL;
//   pp_pkg_subfix_ptr = (char **)&g_pkg_subfix[0];
//   while (NULL != *pp_pkg_subfix_ptr) {
//        if (NULL == *pp_pkg_subfix_ptr) {
//            break;
//        }
//        if (strstr(p_file_name, *pp_pkg_subfix_ptr) != NULL) {
//           return 0;
//       } else {
//           pp_pkg_subfix_ptr++;
//       }
//   }//end while
//--------------error ----------------

    return -1;
}

//typedef gint            (*GCompareFunc)         (gconstpointer  a,
                                                 //gconstpointer  b);

gint cmp_arch_pkg_name(gconstpointer  a, gconstpointer  b)
{
    TArchPkg_t *pkg_a;
    TArchPkg_t *pkg_b;
    pkg_a = (TArchPkg_t *) a;
    pkg_b = (TArchPkg_t *) b;
   //return g_strcmp(pkg_a->pkg_name, pkg_b->pkg_name); 
   return strcmp(pkg_a->pkg_name, pkg_b->pkg_name); 
}

gint cmp_arch_pkg_full_ver(gconstpointer  a, gconstpointer  b)
{
    TArchPkg_t *pkg_a;
    TArchPkg_t *pkg_b;
    pkg_a = (TArchPkg_t *) a;
    pkg_b = (TArchPkg_t *) b;
   //return g_strcmp(pkg_a->pkg_name, pkg_b->pkg_name); 
   return my_alpm_pkg_vercmp(pkg_b->pkg_full_ver, pkg_a->pkg_full_ver); 
}



GList *find_remove_pkgs(GList *pkg_list)
{
    GList *list = NULL;
    GList *tmp_list = NULL;
    
    GList *remove_list = NULL;
    GList *remove_same_pkg_name_list = NULL;
    GList *remove_all_pkg_list = NULL;
    list = pkg_list;
    while (NULL != list) {
        tmp_list = list;
        remove_same_pkg_name_list = NULL;
        list = g_list_remove_link(list, tmp_list);
        do {
            remove_list = g_list_find_custom(list, tmp_list->data, cmp_arch_pkg_name); 
            if (NULL != remove_list) {
                //remove_same_pkg_name_list = g_list_append(remove_same_pkg_name_list, remove_list);
                list = g_list_remove_link(list, remove_list);
                remove_same_pkg_name_list = g_list_concat(remove_list, remove_same_pkg_name_list);
            }
        } while (NULL != remove_list);
        if (NULL != remove_same_pkg_name_list) {
            remove_same_pkg_name_list = g_list_concat(tmp_list , remove_same_pkg_name_list);
            remove_same_pkg_name_list = g_list_sort(remove_same_pkg_name_list , cmp_arch_pkg_full_ver);
            remove_all_pkg_list = g_list_append(remove_all_pkg_list , remove_same_pkg_name_list);
        } else {
            //tmp_list->next = NULL;
            //tmp_list->prev = NULL;
            free_all_list_pkg(tmp_list);
            g_list_free(tmp_list);
        }
        //list = list->next;
    }//end while
    return remove_all_pkg_list;
}

void free_same_pkg_list(gpointer list_data, gpointer user_data)
{
    free_all_list_pkg(list_data);
    g_list_free(list_data);
}

void free_scan_pkgs_list(GList *list)
{
    if (NULL != list) {
        g_list_foreach(list, free_same_pkg_list, NULL);
        g_list_free(list);
    }
}

void show_single_pkg_list_info(GList *list)
{
    guint same_pkg_cnt;
    GList *tmp_list;
    TArchPkg_t *p_arch_pkg;
    g_printf("===============================\n");
    //printf("pkg_name \t= %s\n", p_arch_pkg->pkg_name);
    same_pkg_cnt = g_list_length(list);
    tmp_list = list;
    p_arch_pkg = (TArchPkg_t *) tmp_list->data;
    g_printf("@@@@   pkgname \t= %s   \tsame pkg cnt = %d\n", p_arch_pkg->pkg_name,  same_pkg_cnt);
    while (NULL != tmp_list) {
        p_arch_pkg = (TArchPkg_t *) tmp_list->data;
        g_printf("pkg_full_ver \t= %s\n", p_arch_pkg->pkg_full_ver);
        print_arch_pkg(p_arch_pkg);
        tmp_list = tmp_list->next;
    }//end 
}

void show_single_pkg_list_filename(GList *list)
{
    guint same_pkg_cnt;
    GList *tmp_list;
    TArchPkg_t *p_arch_pkg;
    g_printf("===============================\n");
    //printf("pkg_name \t= %s\n", p_arch_pkg->pkg_name);
    same_pkg_cnt = g_list_length(list);
    tmp_list = list;
    p_arch_pkg = (TArchPkg_t *) tmp_list->data;
    //g_printf("@@@@   pkgname \t= %s   \tsame pkg cnt = %d\n", p_arch_pkg->pkg_name,  same_pkg_cnt);
    while (NULL != tmp_list) {
        p_arch_pkg = (TArchPkg_t *) tmp_list->data;
        g_printf("pkg_file_name \t= %s\n", p_arch_pkg->pkg_file_name);
        tmp_list = tmp_list->next;
    }//end 
}
void delete_single_pkg_list_filename(GList *list, const char *dir_name, gboolean b_unlink_en)
{
    guint same_pkg_cnt;
    char del_filename[255];
    GList *tmp_list;
    TArchPkg_t *p_arch_pkg;
    //printf("===============================\n");
    //printf("pkg_name \t= %s\n", p_arch_pkg->pkg_name);
    same_pkg_cnt = g_list_length(list);
    tmp_list = list;
    p_arch_pkg = (TArchPkg_t *) tmp_list->data;
    //g_printf("@@@@   pkgname \t= %s   \tsame pkg cnt = %d\n", p_arch_pkg->pkg_name,  same_pkg_cnt);
    while (NULL != tmp_list) {
        p_arch_pkg = (TArchPkg_t *) tmp_list->data;
        snprintf(del_filename, sizeof(del_filename), "%s/%s", dir_name, p_arch_pkg->pkg_file_name);
        if (TRUE == b_unlink_en) {
            if (access(del_filename, W_OK) == 0) {
                //g_printf("access(%s, W_OK) == 0\n", del_filename);
                if (!unlink(del_filename)) {
                    g_printf("delete %s success\n", del_filename);
                } else {
                    g_printf("delete %s faile\n", del_filename);
                }
            } else {
                g_printf("!!! access(%s, W_OK) != 0\n", del_filename);
            }
        } else {
            g_printf("rm -f %s\n", del_filename);
            g_printf("++ use c function  unlink(%s)\n", del_filename);
        }
        //printf("pkg_file_name \t= %s\n", p_arch_pkg->pkg_file_name);
        tmp_list = tmp_list->next;
    }//end 
}

void ShowRemovePkgListFileName(GList *list)
{
    guint pkg_cnt;
    GList *tmp_list;
    pkg_cnt = g_list_length(list);
    tmp_list = list;
    while (NULL != tmp_list) {
        show_single_pkg_list_filename(tmp_list->data);
        tmp_list = tmp_list->next;
    }//end
    g_printf("pkg cnt = %d\n", pkg_cnt);
}

void DeleteRemovePkgListFileName(GList *list, const char *dir_name, gboolean b_unlink_en)
{
    guint pkg_cnt;
    GList *tmp_list;
    pkg_cnt = g_list_length(list);
    tmp_list = list;
    while (NULL != tmp_list) {
        delete_single_pkg_list_filename(tmp_list->data, dir_name, b_unlink_en);
        tmp_list = tmp_list->next;
    }//end
    g_printf("pkg cnt = %d\n", pkg_cnt);
}


void ShowRemovePkgListInfo(GList *list)
{
    guint pkg_cnt;
    GList *tmp_list;
    pkg_cnt = g_list_length(list);
    tmp_list = list;
    while (NULL != tmp_list) {
        show_single_pkg_list_info(tmp_list->data);
        tmp_list = tmp_list->next;
    }//end
    g_printf("pkg cnt = %d\n", pkg_cnt);
}


GList *filter_single_pkg_list(GList *list, guint save_num)
{
    guint same_pkg_cnt;
    GList *tmp_list;
    TArchPkg_t *p_arch_pkg;
    g_printf("=========save  package ======================\n");
    //printf("pkg_name \t= %s\n", p_arch_pkg->pkg_name);
    same_pkg_cnt = g_list_length(list);
    tmp_list = list;
    p_arch_pkg = (TArchPkg_t *) tmp_list->data;
    g_printf("@@@@   pkgname \t= %s   \tsame pkg cnt = %d\n", p_arch_pkg->pkg_name,  same_pkg_cnt);
    g_printf("-- save number = %d\n", save_num);
    while (save_num--) {
        p_arch_pkg = (TArchPkg_t *) tmp_list->data;
        g_printf("save pkg_full_ver \t= %s\n", p_arch_pkg->pkg_full_ver);
        arch_pkg_free(p_arch_pkg);
        tmp_list = g_list_delete_link(tmp_list, tmp_list);
        //tmp_list = tmp_list->next;
    }//end
    //tmp_list = tmp_list->next;
    return tmp_list;
}


GList *FilterRemovePkgList(GList *list, guint save_num)
{
    guint pkg_cnt;
    GList *tmp_list;
    pkg_cnt = g_list_length(list);
    g_printf("pkg cnt = %d\n", pkg_cnt);
    tmp_list = list;
    while (NULL != tmp_list) {
        //show_single_pkg_list_info(tmp_list->data);
        tmp_list->data = filter_single_pkg_list(tmp_list->data, save_num);
        if (NULL == tmp_list->data) {
            list = g_list_delete_link(list, tmp_list);    
        } else {
            tmp_list = tmp_list->next;
        }
    }//end
    return list;
}



